﻿using Iot.Hubs;
using Iot.Models;
using Microsoft.AspNetCore.SignalR;
using MQTTnet;
using MQTTnet.Client;
using System.Text.Json;

namespace Iot
{
    public interface IClientWorker
    {
        Task PublishAsync(string topic, MQTTMessage msg);
    }

    public class ClientWorker : BackgroundService, IClientWorker
    {
        private static IMqttClient? client;
        private static ILogger<ClientWorker>? _logger;
        private static IHubContext<MessageHub>? _hubContext;

        public ClientWorker(IServiceProvider provider)
        {
            _logger = provider.GetRequiredService<ILogger<ClientWorker>>();
            _hubContext = provider.GetRequiredService<IHubContext<MessageHub>>();
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await StartMqttClient();
        }

        static async Task StartMqttClient()
        {
            string username = "admin";//用户名
            string password = "admin";//密码
            string clientId = "LocalClient";//客户端名称

            var mqttFactory = new MqttFactory();
            client = mqttFactory.CreateMqttClient();

            var mqttClientOptions = new MqttClientOptionsBuilder()
                .WithClientId(clientId)
                .WithTcpServer("127.0.0.1")
                .WithCredentials(username, password)
                .Build();

            await client.ConnectAsync(mqttClientOptions, CancellationToken.None);

            if (client.IsConnected)
            {
                _logger?.LogInformation($"{DateTime.Now}  {clientId} 已连接到服务器.");
            }
            else
            {
                _logger?.LogError($"{DateTime.Now}  {clientId} 连接服务器失败");

                //5秒后重试
                System.Threading.Thread.Sleep(5000);
                await StartMqttClient();
            }
        }

        public async Task PublishAsync(string topic, MQTTMessage msg)
        {
            if (client != null && client.IsConnected)
            {
                var applicationMessage = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(JsonSerializer.Serialize(msg))
                .Build();

                await client.PublishAsync(applicationMessage, CancellationToken.None);
            }
        }
    }
}
